(function() {
    var _requestIndex = 1;
    var _requestQueue = {}; // 等待响应的请求队列

    var _requestBuffer = []; // 缓冲连接未就绪时的请求

    var _requestSerialization; // 这里始终用最后一个请求的，不支持不同请求的序列化方式不同

    var _queuePut = function(_requestId, _request) {
        console.log('#12 _queuePut', _requestId);

        _requestQueue["request-" + _requestId] = _request; // 加入队列等待回调
    };

    var _queueGet = function(_requestId) {
        return _requestQueue["request-" + _requestId]; // 从队列中取出请求
    };

    var _queueDelete = function(_requestId) {
        console.log('#20 _queueDelete', _requestId);

        delete _requestQueue["request-" + _requestId]; // 从队列中移除
    };

    // 收消息回调
    var _onMessage = function(_messageEvent) {
        console.log('#27 _onMessage', _messageEvent);

        var _responseEntity = _requestSerialization.deserialize(_messageEvent.data); // 反序列化

        var _requestId = _responseEntity.requestId;
        var _request = _queueGet(_requestId); // 从队列中取出请求

        if (!!!_request) {
            console.error('#35 req not found', _requestId, _requestQueue);
        }

        var _responseBody = _responseEntity.result;
        _request.responseBody = _responseBody;

        _request.responseHandler(_request); // 执行回调

        _queueDelete(_requestId); // 从队列中移除
    };

    // 封装发消息，如果未就绪，就加入缓冲
    var _sendMessage = function(_requestMessage) {
        console.log('#48 _sendMessage', _requestMessage);

        var _ws = _getWebsocket();
        if ( !!_ws ) {
            console.log('#52 _sendMessage', _ws);
            _ws.send(_requestMessage); // 发请求消息
        }

        console.log('#51 _sendMessage', _requestMessage);
        _requestBuffer.push(_requestMessage);
    };

    var _onError = function(a) {
        console.log('#56 _onError', a);
    };

    // 连接就绪后，发送缓冲区的请求
    var _onOpen = function(event) {
        console.log('#61 _onOpen', event);

        _requestBuffer.forEach(function(_req) {
            console.log('#63 _onOpen forEach _send _onOpen', _req);
            _sendMessage(_req);
        });

        var _ws = _getWebsocket();
        // _ws.send(); // 发 handshake
        // _ws.send(); // 

        _requestBuffer = [];
    };

    // CONNECTING：值为0，表示正在连接。
    // OPEN：值为1，表示连接成功，可以通信了。
    // CLOSING：值为2，表示连接正在关闭。
    // CLOSED：值为3，表示连接已经关闭，或者打开连接失败。
    var _getWebsocket = function() {
        if ( !!window._websocket ) {
            return window._websocket;
        }

        console.log('#77 init _websocket', window._websocket);

        var _url = "ws://" + location.host + "/ws"; // 完整路径
        window._websocket = new WebSocket(_url);
        window._websocket.onopen = _onOpen;
        window._websocket.onerror = _onError;
        window._websocket.onmessage = _onMessage;
        return window._websocket;
    };

    // 发消息
    var WebSocketTransporter = function(_request) {
        var _requestId = _requestIndex++;
        _queuePut(_requestId, _request);

        var _requestEntity = {
            "requestId" : _requestId,
            "interfaceName" : _request.interfaceName,
            "methodName" : _request.methodName,
            "args" : _request.args
        };

        _requestSerialization = _request.serialization; // 保存，返回时会使用
        var _requestMessage = _requestSerialization.serialize(_requestEntity);
        _sendMessage(_requestMessage);
    };

    // 挂载根对象
    var _root = null;

    if (!!window) {
        _root = window; // 浏览器环境, 挂载到window
    } else if (!!wx) {
        _root = wx; // 微信小程序, 挂载到wx
    } else {
        throw "window or wx not found, contact the developer now";
    }

    // 自动初始化
    _getWebsocket();

    _root.WebSocketTransporter = WebSocketTransporter;
})();